package org.cybzacg.convert.converters.date;

import lombok.extern.slf4j.Slf4j;
import org.cybzacg.convert.annotation.Converter;
import org.cybzacg.convert.constants.DateFormats;
import org.cybzacg.convert.constants.DateTimeDefaults;
import org.cybzacg.convert.context.ConversionContext;
import org.cybzacg.convert.enums.ConversionPriority;
import org.cybzacg.convert.enums.ConversionType;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;

/**
 * ZonedDateTime转换器
 * 专门处理ZonedDateTime类型的转换
 *
 * @author cybzacg.blog
 * @version 4.0
 * @since 3.0
 */
@Slf4j
@Converter(name = "ZonedDateTimeConverter", priority = ConversionPriority.MEDIUM_HIGH, description = "ZonedDateTime类型转换器，处理各种类型到java.time.ZonedDateTime的转换", version = "4.0", author = "cybzacg.blog", supportedTypes = {
        ZonedDateTime.class }, tags = { "zoneddatetime", "time", "conversion" })
public class ZonedDateTimeConverter extends AbstractDateTimeConverter<ZonedDateTime> {

    public ZonedDateTimeConverter() {
        super(ZonedDateTime.class, ConversionPriority.MEDIUM_HIGH);
    }

    @Override
    protected ConversionType getConversionType() {
        return ConversionType.ZONED_DATE_TIME;
    }

    @Override
    protected ZonedDateTime parseFromString(String str, DateTimeFormatter formatter) throws DateTimeParseException {
        // 先尝试解析为 ZonedDateTime
        try {
            return ZonedDateTime.parse(str, formatter);
        } catch (DateTimeParseException e) {
            // 尝试解析为 LocalDateTime 然后添加时区
            try {
                LocalDateTime localDateTime = LocalDateTime.parse(str, formatter);
                return localDateTime.atZone(DEFAULT_ZONE_ID);
            } catch (DateTimeParseException ex) {
                // 最后尝试解析为 LocalDate 然后转换
                LocalDate localDate = LocalDate.parse(str, formatter);
                return localDate.atStartOfDay(DEFAULT_ZONE_ID);
            }
        }
    }

    @Override
    protected ZonedDateTime convertFromInstant(java.time.Instant instant, ConversionContext context) {
        return ZonedDateTime.ofInstant(instant, DEFAULT_ZONE_ID);
    }

    @Override
    protected String[] getSupportedPatterns() {
        // 合并时区、日期时间和日期格式
        String[] timezonePatterns = DateFormats.TIMEZONE_FORMAT_PATTERNS;
        String[] datetimePatterns = DateFormats.DATETIME_FORMAT_PATTERNS;
        String[] datePatterns = DateFormats.DATE_FORMAT_PATTERNS;

        String[] allPatterns = new String[timezonePatterns.length + datetimePatterns.length + datePatterns.length];
        int pos = 0;
        System.arraycopy(timezonePatterns, 0, allPatterns, pos, timezonePatterns.length);
        pos += timezonePatterns.length;
        System.arraycopy(datetimePatterns, 0, allPatterns, pos, datetimePatterns.length);
        pos += datetimePatterns.length;
        System.arraycopy(datePatterns, 0, allPatterns, pos, datePatterns.length);

        return allPatterns;
    }

    @Override
    protected ZonedDateTime convertFromOtherDateTime(Object source, ConversionContext context) {
        // LocalDateTime转换
        if (source instanceof LocalDateTime localDateTime) {
            return localDateTime.atZone(DEFAULT_ZONE_ID);
        }

        // LocalDate转换
        if (source instanceof LocalDate localDate) {
            return localDate.atStartOfDay(DEFAULT_ZONE_ID);
        }

        // LocalTime转换
        if (source instanceof LocalTime localTime) {
            return LocalDate.now().atTime(localTime).atZone(DEFAULT_ZONE_ID);
        }

        // Year转换
        if (source instanceof Year year) {
            return year.atDay(1).atStartOfDay(DEFAULT_ZONE_ID);
        }

        // YearMonth转换
        if (source instanceof YearMonth yearMonth) {
            return yearMonth.atDay(1).atStartOfDay(DEFAULT_ZONE_ID);
        }

        return null;
    }

    @Override
    protected ZonedDateTime getDefaultValue() {
        return DateTimeDefaults.ZONED_DATETIME_DEFAULT;
    }
}
